#include "SnifferManager.h"
#include "eutranCtrl.h"
#include "EutranConfigData.h"
#include "ProcedureCtrl.h"

#include <algorithm>

SnifferProcedure::SnifferProcedure(BbuCtrl* bbu):
bbuPtr_(bbu),
isPrepareing_(false),
isActive_(false),
sentSeqNo_(0),
waitBbuConnTimer_(210),
waitBbuConnHandler_(this, &SnifferProcedure::bbuConnTimeout),
snfTrigger_(INVALID_SNF_TRIGGER)
{
}

SnifferProcedure::~SnifferProcedure()
{
}

void SnifferProcedure::bbuConnTimeout()
{
    EMLogWarning("BBU[%d]: time out to wait BBU connection, break SNF", bbuPtr_->getInstance().getSlotId());

    stopProcedure();
    SnifferMgrPtr->openTxPwer();
}

void SnifferProcedure::prepare()
{
    isPrepareing_ = true;
}

void SnifferProcedure::waitForBbuConn()
{
    EutranTimerPtr->queue(waitBbuConnTimer_, &waitBbuConnHandler_);
}

void SnifferProcedure::stopBbuConnTimer()
{
    if( waitBbuConnHandler_.isQueue_ )
    {
        EMLogInfo("BBU[%d]: Deque BBU conn timer", bbuPtr_->getInstance().getSlotId());
        EutranTimerPtr->dequeue(&waitBbuConnHandler_);
    }
}

bool SnifferProcedure::startSniffer()
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    NmmToX86Protocol_SnifferStart startMsg;
    sentSeqNo_ = bbuPtr_->getInstance().allocSeqNo();
    startMsg.packSeqNum(sentSeqNo_);

    const std::vector<uint16_t>* pciListPtr = NULL;
    if( !pciList_.empty() )
    {
        pciListPtr = &pciList_;
    }

    uint8_t rptStrategy = SnifferMgrPtr->getSnifferReportStrategy();
    if( !startMsg.pack(pciListPtr, arfcnRange_, EutranConfigDataPtr->getRssiThreshold(bbuPtr_->getInstance().getSlotId()), &rptStrategy) )
    {
        EMLogError("Fail to pack NmmToX86Protocol_SnifferStart");
        return false;
    }

    if( !bbuPtr_->getInstance().sendMessage(startMsg.getMessage()) )
    {
        return false;
    }
    
    isActive_ = true;
    isPrepareing_ = false;

    return true;
}

bool SnifferProcedure::processSnifferResult(NmmToX86Protocol_SnifferResultReport& report)
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    uint32_t recvSeqNo = 0;
    if( !report.unpackSeqNum(recvSeqNo) )
    {
        EMLogWarning("Fail to unpack SeqNo");
    }
 
    std::vector<NmmResult> results;

    NmmToX86Protocol_SnifferResultReportRsp rsp;
    rsp.packSeqNum(recvSeqNo);
    bbuPtr_->getInstance().sendMessage(rsp.getMessage());
    
    if( !report.unpack(results) )
    {
        EMLogWarning("Fail to unpack NmmToX86Protocol_SnifferResultReport");
        return false;
    }

    EMLogInfo("BBu[%d]: Receive num of sniffer results[%d] from slotId[%d]", bbuPtr_->getInstance().getSlotId(), results.size(), bbuPtr_->getInstance().getSlotId());

    SnifferMgrPtr->addResults(bbuPtr_->getInstance().getSlotId(), results);
    return true;
}

bool SnifferProcedure::processResultEnd(NmmToX86Protocol_SnifferResultReportEnd& endRpt)
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    EMLogInfo("BBU[%d]: process SNF result end message in SNF procedure", bbuPtr_->getInstance().getSlotId());
    if( !isActive_ )
    {
        EMLogWarning("Receive SnifferResultReportEnd in invalid state");
        return false;
    }

    uint32_t recvSeqNo = 0;

    if( !endRpt.unpackSeqNum(recvSeqNo) )
    {
        EMLogWarning("Fail to unpack SeqNo");
    }
    NmmToX86Protocol_SnifferResultReportEndRsp endRsp;
    endRsp.packSeqNum(recvSeqNo);
    bbuPtr_->getInstance().sendMessage(endRsp.getMessage());
    
    isActive_ = false;
    isPrepareing_ = false;
    arfcnRange_.clear();
    pciList_.clear();

    StateReportProcedurePtr->reportState(*bbuPtr_, BBU_READY);
    return true;
}

bool SnifferProcedure::processSnifferStartRsp(NmmToX86Protocol_SnifferStartRsp& rsp)
{
    if( !isActive_ )
    {
        EMLogWarning("Receive SnifferStartRsp in invalid state");
        return false;
    }

    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    
    uint32_t recvSeqNo = 0;

    if( !rsp.unpackSeqNum(recvSeqNo) )
    {
        EMLogWarning("Fail to unpack SeqNo");
    }
    if( recvSeqNo!=sentSeqNo_ )
    {
        EMLogWarning("recvSeqNo[%d] is not equal to sentSeqNo[%d]", recvSeqNo, sentSeqNo_);
    }

    uint8_t rc = 0;
    if( !rsp.unpack(rc) )
    {
        EMLogWarning("Fail to unpack NmmToX86Protocol_SnifferStartRsp");
        return false;
    }

    if( rc==0 )
    {
        EMLogInfo("BBU[%d]: Receive SnifferStartRsp", bbuPtr_->getInstance().getSlotId());
        StateReportProcedurePtr->reportState(*bbuPtr_, BBU_SNFING);
    }
    else
    {
        EMLogInfo("Fail to start sniffer, rc=%d", static_cast<uint32_t>(rc));
        stopProcedure();
        SnifferMgrPtr->openTxPwer();
        return false;
    }
    return true;
}

bool SnifferProcedure::processSnifferStopRsp(NmmToX86Protocol_SnifferStopRsp& rsp)
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    EMLogInfo("BBU[slot-id=%d] Receive sniffer stop rsp", bbuPtr_->getInstance().getSlotId());

    uint32_t recvSeqNo = 0;

    if( !rsp.unpackSeqNum(recvSeqNo) )
    {
        EMLogWarning("Fail to unpack seq no");
    }

    if( recvSeqNo!=sentSeqNo_ )
    {
        EMLogWarning("recvSeqNo[%d] is not equal to sentSeqNo_[%d]", recvSeqNo, sentSeqNo_);
    }
    isActive_ = false;
    isPrepareing_ = false;
    arfcnRange_.clear();
    pciList_.clear();
    sentSeqNo_ = 0;
    return true;
}

bool SnifferProcedure::stopSniffer()
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }
    NmmToX86Protocol_SnifferStop stop;
    sentSeqNo_ = bbuPtr_->getInstance().allocSeqNo();
    stop.packSeqNum(sentSeqNo_);
    if( !bbuPtr_->getInstance().sendMessage(stop.getMessage()) )
    {
        EMLogError("Fail to send SnifferStop");
    }

    return true;
}

void SnifferProcedure::stopProcedure()
{
    EMLogInfo("BBU[%d]: stop sniffer procedure", bbuPtr_->getInstance().getSlotId());
    
    isActive_ = false;
    isPrepareing_ = false;
    arfcnRange_.clear();
    pciList_.clear();
    sentSeqNo_ = 0;
    snfTrigger_ = INVALID_SNF_TRIGGER;
}

bool SnifferProcedure::isActive()
{
    return isActive_ || isPrepareing_;
}

bool SnifferProcedure::isPrepare()
{
    return isPrepareing_;
}
/*
const char *SnfState::stateString[] =
{
    "INVALID",
    "IDLE",
    "PREPARE",
    "PROCEED"
    "END"
};

SnfState::SnfState(StateType stateType):
stateType_(stateType)
{
}

void SnfState::changeState(SnfState* state)
{
    EMLogInfo("SnfState::changeState: old [%s] to new [%s]",
              this->getStateString(),
              state->getStateString());
    NmmSnifferCtrlPtr->changeState(nmmState);
}

bool SnfState::processTxPwerRsp(BbuCtrl&, OamMessageProtocol_TxPowerRsp& rsp)
{
    EMLogInfo("Receive TxPwerRsp msg in %s, ignore.", stateString[stateType_]);
    return true;
}

bool SnfState::processBbuStateRsp(BbuCtrl&, OamMessageProtocol_SysStatusRsp& rsp)
{
    EMLogInfo("Receive BbuStateRsp msg in %s, ignore.", stateString[stateType_]);
    return true;
}

SnfIdleState::SnfIdleState():
SnfState(SNF_IDLE_STATE)
{
}

SnfState* SnfIdleState::instance()
{
    static SnfIdleState instance_;
    return &instance_;
}

SnfPrepareState::SnfPrepareState():
SnfState(SNF_PREPARE_STATE)
{
}

SnfState* SnfPrepareState::instance()
{
    static SnfPrepareState instance_;
    return &instance_;
}

bool SnfPrepareState::processBbuStateRsp(BbuCtrl& bbu, OamMessageProtocol_SysStatusRsp& rsp)
{
    uint32_t stateCode = 0;

    if( !rsp.unpack(stateCode) )
    {
        EMLogError("BBU[%d]: Fail to decode OamMessageProtocol_SysStatusRsp", bbu.getInstance().getSlotId());

        changeState(SnfIdleStatePtr);
        return false;
    }

    if( stateCode==4 || stateCode==5 )
}

bool SnfPrepareState::processTxPwerRsp(BbuCtrl&, OamMessageProtocol_TxPowerRsp& rsp)
{
    bool isAllConfigFinish = false;

    if( isAllConfigFinish )
    {
        changeState(SnfProceedState);

        SnifferProcedure* pro = NULL;
        pro->startSniffer();
    }
    else
    {
        // wait 
    }
    return true;
}

SnfProceedState::SnfProceedState():
SnfState(SNF_PROCEED_STATE)
{
}

SnfState* SnfProceedState::instance()
{
    static SnfProceedState instance_;
    return &instance_;
}*/

SnfPrepareProcedure::SnfPrepareProcedure():
isActive_(false),
snfBbuId_(0)
{
}

bool SnfPrepareProcedure::start(uint8_t slotId)
{
    if( slotId==0 || slotId>BbuManager::MAX_BBU_INSTANCES )
    {
        EMLogError("Slot-id[%d] is out of range", static_cast<uint32_t>(slotId));
        return false;
    }

    EMLogInfo("BBU[%d]: Start sniffer prepare procedure", slotId);
    
    snfBbuId_ = slotId;
    slotIdToBeHandle_.clear();
    BbuManagerPtr->getIdOfActiveBbus(slotIdToBeHandle_);

    if( slotIdToBeHandle_.empty() )
    {
        EMLogError("No available BBU");
        return false;
    }

    for(std::set<uint32_t>::iterator it=slotIdToBeHandle_.begin(); it!=slotIdToBeHandle_.end(); it++)
    {
        uint8_t slotId = static_cast<uint8_t>(*it);
        BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
        if( bbu==NULL )
        {
            EMLogError("BBU ctrl pointer is NULL, slotId=%d", static_cast<uint32_t>(slotId));
            return false;
        }

        bbu->buildAndSendBbuStateReq();
    }

    isActive_ = true;
    return true;
}

bool SnfPrepareProcedure::stop()
{
    EMLogInfo("SnfPrepareProcedure::stop");
    
    snfBbuId_ = 0;
    slotIdToBeHandle_.clear();
    isActive_ = false;
    return true;
}

bool SnfPrepareProcedure::isProcedureDone()
{
    return slotIdToBeHandle_.empty();
}

bool SnfPrepareProcedure::isActive()
{
    return isActive_;
}

bool SnfPrepareProcedure::processTxPwerDbRsp(BbuCtrl& bbu, OamMessageProtocol_TxPowerDbmConfigRsp& rsp)
{
    std::set<uint32_t>::iterator idIt = slotIdToBeHandle_.find(bbu.getInstance().getSlotId());

    if( idIt==slotIdToBeHandle_.end() )
    {
        EMLogWarning("BBU[%d] is not found in slotIdToBeHandle_", bbu.getInstance().getSlotId());
        return true;
    }

    slotIdToBeHandle_.erase(idIt);

    if( isProcedureDone() )
    {
        EMLogInfo("SnfPrepareProcedure is done");
        
        SnifferMgrPtr->startSnf(snfBbuId_);
        stop();
    }
    return true;
}

bool SnfPrepareProcedure::processBbuStateRsp(BbuCtrl& bbu, OamMessageProtocol_SysStatusRsp& rsp)
{
    EMLogInfo("BBU[%d]: process BBU state respons in SNF prepare procedure", bbu.getInstance().getSlotId());
    std::set<uint32_t>::iterator idIt = slotIdToBeHandle_.find(bbu.getInstance().getSlotId());

    if( idIt==slotIdToBeHandle_.end() )
    {
        EMLogWarning("BBU[%d] is not found in slotIdToBeHandle_", bbu.getInstance().getSlotId());
        return true;
    }

    uint32_t stateCode = 0;
    if( !rsp.unpack(stateCode) )
    {
        EMLogError("BBU[%d]: Fail to unpack OamMessageProtocol_SysStatusRsp", bbu.getInstance().getSlotId());
    }

    if( stateCode==4 || stateCode==5 )
    {
        EMLogInfo("BBU[%d]: BBU is working", bbu.getInstance().getSlotId());

        if( *idIt==snfBbuId_ )
        {
            EMLogInfo("Reboot BBU[%d] before sniffer", *idIt);

            std::string des = "Reboot before sniffer as in working state";
            bbu.handleCtrlPA(false, BbuCtrl::REBOOT);
        }
        else
        {
            if( !bbu.buildAndSendTxPowerDb(127) )
            {
                EMLogError("BBU[%d]: Fail to send TxPower", bbu.getInstance().getSlotId());
                return false;
            }
        }
    }
    else 
    {
        EMLogInfo("BBU[%d] is not working", bbu.getInstance().getSlotId());
        slotIdToBeHandle_.erase(idIt);
    }

    if( isProcedureDone() )
    {
        EMLogInfo("SnfPrepareProcedure is done");
        
        SnifferMgrPtr->startSnf(snfBbuId_);
        stop();
    }

    return true;
}

void SnfPrepareProcedure::indicateBbuDeactive(BbuCtrl& bbu)
{
    std::set<uint32_t>::iterator idIt = slotIdToBeHandle_.find(bbu.getInstance().getSlotId());

    if( idIt==slotIdToBeHandle_.end() )
    {
        EMLogInfo("BBU[%d]: New BBU connects, not in slotIdToBeHandleList", bbu.getInstance().getSlotId());
        return;
    }
    else
    {
        EMLogInfo("BBU[%d]: Become deactive", bbu.getInstance().getSlotId());
        if( snfBbuId_!=bbu.getInstance().getSlotId() )
        {
            slotIdToBeHandle_.erase(idIt);
        }
    }

    if( isProcedureDone() )
    {
        EMLogInfo("SnfPrepareProcedure is done");
        
        SnifferMgrPtr->startSnf(snfBbuId_);
        stop();
    }
}

uint32_t SnfPrepareProcedure::getSnfBbuId()
{
    return snfBbuId_;
}

SnifferMgr::SnifferMgr():
isAutoCfgCell_(true),
isCurrentProcTrigByOam_(false)
{
};

SnifferMgr* SnifferMgr::instance()
{
    static SnifferMgr instance_;
    return &instance_;
}

bool SnifferMgr::initialize()
{
    EMLogInfo("SnifferMgr::initialize");
    for(uint32_t i=0; i<BbuManager::MAX_BBU_INSTANCES; i++)
    {
        uint8_t slotId = i+1;
        procedures_[i] = new SnifferProcedure(BbuManagerPtr->getBbu(slotId));
        if( procedures_[i]==NULL )
        {
            EMLogError("Fail to allocate memory");
            return false;
        }
        if( procedures_[i]->bbuPtr_==NULL )
        {
            EMLogError("Fail to allocate memory");
            return false;
        }

        autoSnfCtrls_[i] = new AutoSnifferCtrl(BbuManagerPtr->getBbu(slotId));
        if( autoSnfCtrls_[i]==NULL )
        {
            EMLogError("Fail to allocate memory");
            return false;
        }
        if( autoSnfCtrls_[i]->bbuPtr_==NULL )
        {
            EMLogError("Fail to allocate memory");
            return false;
        }
    }
    return true;
}

bool SnifferMgr::startSniffer(SnifferTriggerType trgType, uint8_t slotId, const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList)
{
    EMLogInfo("BBU[%d]: Start sniffer with trgType[%d]", static_cast<uint32_t>(slotId), trgType);

    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    if( bbu==NULL )
    {
        EMLogError("BBU ctrl pointer is NULL, slotId=%d", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !bbu->getInstance().isActive() )
    {
        EMLogError("BBU[%d]: BBU is deactive", static_cast<uint32_t>(slotId));
        return false;
    }

    SnifferProcedure* pro = procedures_[slotId-1];
    if( pro->isActive() )
    {
        EMLogError("BBU[%d]: SnifferProcedure is active", bbu->getInstance().getSlotId());
        return false;
    }

    if( prepareProc_.isActive() )
    {
        EMLogWarning("BBU[%d]: BBU[%d] is in sniffre prepare phase", bbu->getInstance().getSlotId(), prepareProc_.getSnfBbuId());
        return false;
    }

    pro->snfTrigger_ = trgType;
    
    std::copy(range.begin(), range.end(), std::back_inserter(pro->arfcnRange_));

    if( pciList!=NULL )
    {
        std::copy(pciList->begin(), pciList->end(), std::back_inserter(pro->pciList_));
    }

    pro->prepare();

    snifferResults_[slotId-1].clear();

    if( !prepareProc_.start(slotId) )
    {
        prepareProc_.stop();
        pro->stopProcedure();

        
        EutranMgrPtr->responseFailure();
        return false;
    }
    else
    {
        EutranMgrPtr->responseSuccess();
        return true;
    }
}

bool SnifferMgr::startSnf(uint8_t slotId)
{
    if( !BbuManagerPtr->isSlotIdValid(slotId) )
    {
        return false;
    }
    
    SnifferProcedure* pro = procedures_[slotId-1];

    return pro->startSniffer();
}
/*{
    std::set<uint32_t> idOfactiveBbus;
    BbuManagerPtr->getIdOfActiveBbus(idOfactiveBbus);

    if( idOfactiveBbus.empty() )
    {
        EMLogInfo("No available BBU");
        return false;
    }

    uint8_t slotId = *(idOfactiveBbus.begin());
    
    EMLogInfo("Use BBU[slot=%d] to start sniffer", static_cast<uint32_t>(slotId));
    
    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    if( bbu==NULL )
    {
        EMLogError("BBU ctrl pointer is NULL, slotId=%d", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !bbu->getInstance().isActive() )
    {
        EMLogError("BBU[slotId=%d] is deactive", static_cast<uint32_t>(slotId));
        return false;
    }

    SnifferProcedure* pro = procedures_[slotId-1];
    if( pro->isActive() )
    {
        EMLogError("SnifferProcedure is active");
        return false;
    }
    
    std::copy(range.begin(), range.end(), std::back_inserter(pro->arfcnRange_));

    if( pciList!=NULL )
    {
        std::copy(pciList->begin(), pciList->end(), std::back_inserter(pro->pciList_));
    }

    if( !pro->startSniffer() )
    {
        return false;
    }

    allSnifferResults_.clear();
    return true;
}*/

bool SnifferMgr::startSnifferToDiffBbs(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList)
{/*
    std::set<uint32_t> idOfactiveBbus;
    BbuManagerPtr->getIdOfActiveBbus(idOfactiveBbus);
    if( idOfactiveBbus.empty() )
    {
        EMLogError("No active BBU");
        return false;
    }

    uint32_t offset = calNumOfArfcn(range) / idOfactiveBbus.size();

    std::vector<uint32_t> noOfArfcnPerRange;
    if( !calNumOfArfcnPerRange(range, noOfArfcnPerRange) )
    {
        return false;
    }

    uint32_t noOfStoredArfcn = 0;
    uint32_t round = 0;
    for(size_t i=0; i<noOfArfcnPerRange.size(); i++)
    {
        uint32_t tmpNo = noOfStoredArfcn + noOfArfcnPerRange[i];
        if( noOfStoredArfcn==0 )
        {
            if( noOfArfcnPerRange[i]==offset )
            {
                //this procedure push_back
                // go to next procedure
                continue;
            }
            else if( noOfArfcnPerRange[i] < offset )
            {
                noOfStoredArfcn = noOfArfcnPerRange[i];
                // this procedure push_back
                // go to next range
                continue;
            }
            else
            {
                noOfStoredArfcn = offset;
                // this procedure push_back;
                // next procedure go to next round
                continue;
            }
        }
    }

    std::set<uint32_t>::iterator it=idOfactiveBbus.begin();

    uint32_t noOfStoredArfcn = 0;
    for(size_t i=0; i<range.size(); i++)
    {
        if( range[i].first > range[i].second )
        {
            EMLogError("Invalid range[%d - %d]", range[i].first, range[i].second);
            continue;
        }

        uint32_t num = range[i].second - range[i].first + 1;
        if( noOfStoredArfcn==0 )
        {
        }
    }
    */
    return false;
}

bool SnifferMgr::stopSniffer()
{
    if( !isSniffering() )
    {
        EMLogInfo("No active sniffer procedure");
        return true;
    }

    for(uint8_t i=0; i<BbuManager::MAX_BBU_INSTANCES; i++)
    {
        if( procedures_[i]->isActive() )
        {
             procedures_[i]->stopSniffer();
        }
    }
    
    return true;
}

bool SnifferMgr::resetSniffer()
{
    EMLogInfo("SnifferMgr::resetSniffer");
    for(uint8_t i=0; i<BbuManager::MAX_BBU_INSTANCES; i++)
    {
        if( procedures_[i]->isActive() )
        {
             procedures_[i]->stopProcedure();
        }
    }
    prepareProc_.stop();

    std::set<uint32_t> slotIdOfActiveBbu;
    BbuManagerPtr->getIdOfActiveBbus(slotIdOfActiveBbu);

    for(std::set<uint32_t>::iterator it=slotIdOfActiveBbu.begin(); it!=slotIdOfActiveBbu.end(); it++)
    {
        uint8_t slotId = *it;
        BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
        if( bbu==NULL )
        {
            EMLogError("Fail to get BBU from slot-id[%d]", static_cast<uint32_t>(*it));
            continue;
        }
        if( bbu->getInstance().isActive() )
        {
            NmmToX86Protocol_SnifferReset reset;
            reset.packSeqNum(bbu->getInstance().allocSeqNo());
            
            if( !bbu->getInstance().sendMessage(reset.getMessage()) )
            {
                EMLogError("Fail to send SnifferReset to BBU[slot-id=%d]", bbu->getInstance().getSlotId());
            }
        }
    }

    return true;
}

SnifferMgr* SnifferMgr::setAutoCfgCellFlag(bool autoCfg)
{
    EMLogInfo("isAutoCfgCell_ change from [%d] to [%d]", isAutoCfgCell_, autoCfg);
    isAutoCfgCell_ = autoCfg;
    return this;
}

bool SnifferMgr::getAutoCfgCellFlag()
{
    return isAutoCfgCell_;
}

SnifferMgr* SnifferMgr::setSnifferReportStrategy(SnifferResultReportStrategy rptStrategy)
{
    EMLogInfo("Sniffer result report strategy change from [%d] to [%d]", 
               static_cast<uint32_t>(rptStrategy_), static_cast<uint32_t>(rptStrategy));
    rptStrategy_ = rptStrategy;

    return this;
}

uint8_t SnifferMgr::getSnifferReportStrategy()
{
    return rptStrategy_;
}

bool SnifferMgr::isSniffering(uint8_t slotId)
{
    if( slotId!=0 && slotId<=BbuManager::MAX_BBU_INSTANCES )
    {
        return procedures_[slotId-1]->isActive();
    }
    
    for(uint32_t i=0; i<BbuManager::MAX_BBU_INSTANCES; i++)
    {
        if( procedures_[i]->isActive() )
        {
            return true;
        }
    }
    return false;
}

bool SnifferMgr::requestBbuSnifferStatus(uint8_t slotId)
{
    if( slotId==0 || slotId>BbuManager::MAX_BBU_INSTANCES )
    {
        EMLogError("Slot-id[%d] is out of range", static_cast<uint32_t>(slotId));
        return false;
    }

    BbuCtrl* ctrl = BbuManagerPtr->getBbu(slotId);
    if( ctrl==NULL )
    {
        EMLogError("Fail to get BBU from slot-id[%d]", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !ctrl->getInstance().isActive() )
    {
        if( isCurrentProcTrigByOam_ )
        {
            isCurrentProcTrigByOam_ = false;
            std::vector < WrapperCmdPara > responseParas;
            responseParas.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_UNAVAIL)));
            EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, responseParas);
            return true;
        }
    }
    else
    {
        if( ctrl->buildAndSendSnifferStatusReq() )
        {
            return true;
        }
    }
    return false;
}

SnifferMgr* SnifferMgr::procedureTrigByOam(bool isTrg)
{
    isCurrentProcTrigByOam_ = isTrg;
    return this;
}

uint32_t SnifferMgr::calNumOfArfcn(const std::vector<EarfcnRangeType>& range)
{
    uint32_t totalNum = 0;
    for(size_t i=0; i<range.size(); i++)
    {
        if( range[i].first > range[i].second )
        {
            EMLogError("Invalid range of [%d - %d]", range[i].first, range[i].second);
            continue;
        }
        totalNum = range[i].second - range[i].first + 1;
    }
    return totalNum;
}

void SnifferMgr::addResults(uint8_t slotId, std::vector<NmmResult>& results)
{
    if( !BbuManagerPtr->isSlotIdValid(slotId) )
    {
        return;
    }
    std::copy(results.begin(), results.end(), std::back_inserter(snifferResults_[slotId-1]));
}

uint32_t SnifferMgr::calNumOfArfcn(const EarfcnRangeType& range)
{
    return range.second - range.first + 1;
}


bool SnifferMgr::calNumOfArfcnPerRange(const std::vector<EarfcnRangeType>& range, std::vector<uint32_t>& num)
{
    num.clear();
    num.reserve(200);

    for(size_t i=0; i<range.size(); i++)
    {
        if( range[i].first > range[i].second )
        {
            EMLogError("Invalid earfcn range [%d - %d]", range[i].first, range[i].second);
            return false;
        }

        num.push_back(range[i].second-range[i].first+1);
    }
    return true;
}

void SnifferMgr::handleNmmMessage(TlvMessage& tlvmsg, BbuCtrl& bbu)
{
    EMLogInfo("BBU[%d] handleNmmMessage", bbu.getInstance().getSlotId());
    SnifferProcedure* pro = procedures_[bbu.getInstance().getSlotId()-1];

    switch(tlvmsg.getSignalType())
    {
        case NmmToX86Protocol_Signal::SNIFFER_START_RSP:
        {
            if( !pro->isActive() )
            {
                EMLogWarning("SnifferProcedure of BBU[slot-id=%d] is deactive", bbu.getInstance().getSlotId());
                break;
            }
            NmmToX86Protocol_SnifferStartRsp startRsp(tlvmsg);
            bool rc = pro->processSnifferStartRsp(startRsp);

            if( !rc )
            {
                EMLogWarning("BBU[%d]: Fail to start sniffer", bbu.getInstance().getSlotId());
                pro->stopProcedure();
            }
            break;
        }
        case NmmToX86Protocol_Signal::SNIFFER_STOP_RSP:
        {
            if( !pro->isActive() )
            {
                EMLogWarning("SnifferProcedure of BBU[slot-id=%d] is deactive", bbu.getInstance().getSlotId());
                break;
            }
            EMLogInfo("Receive SNIFFER_STOP_RSP from BBU[slot-id=%d]", bbu.getInstance().getSlotId());
            NmmToX86Protocol_SnifferStopRsp rsp(tlvmsg);
            pro->processSnifferStopRsp(rsp);

            
            break;
        }
        case NmmToX86Protocol_Signal::SNIFFER_REST_RSP:
        {
            if( !pro->isActive() )
            {
                EMLogInfo("SnifferProcedure of BBU[slot-id=%d] is deactive", bbu.getInstance().getSlotId());
            }

            EMLogInfo("Receive SNIFFER_REST_RSP from BBU[slot-id=%d]", bbu.getInstance().getSlotId());
            break;
        }
        case NmmToX86Protocol_Signal::SNIFFER_RESULT_REPORT:
        {
            if( !pro->isActive() )
            {
                EMLogWarning("SnifferProcedure of BBU[slot-id=%d] is deactive", bbu.getInstance().getSlotId());
                break;
            }
            
            NmmToX86Protocol_SnifferResultReport resultRpt(tlvmsg);
            pro->processSnifferResult(resultRpt);
            break;
        }
        case NmmToX86Protocol_Signal::SNIFFER_RESULT_REPORT_END:
        {
            if( !pro->isActive() )
            {
                EMLogWarning("SnifferProcedure of BBU[slot-id=%d] is deactive", bbu.getInstance().getSlotId());
                break;
            }
            
            NmmToX86Protocol_SnifferResultReportEnd end(tlvmsg);
            pro->processResultEnd(end);

            handleSnfResult(bbu);

            pro->stopProcedure();
            openTxPwer();
            break;
        }
        case NmmToX86Protocol_Signal::NMM_STATUS_REPORT:
        {
            EMLogInfo("Receive NMM_STATUS_REPORT from BBU[slot-id=%d]", bbu.getInstance().getSlotId());
            NmmToX86Protocol_NmmStatusRpt rpt(tlvmsg);            
            processNmmStatusResponse(rpt);
            break;
        }
        default:
        {
            EMLogError("Unknown message type[%d]", static_cast<uint32_t>(tlvmsg.getSignalType()));
            break;
        }
    }
}

void SnifferMgr::generateIntraFreqNbrList(BbuCtrl& bbu, uint16_t earfcn, std::vector<uint16_t>& intraFreqNbrPciList)
{
    uint8_t slotId = bbu.getInstance().getSlotId();
    for( std::vector<NmmResult>::iterator it = snifferResults_[slotId-1].begin(); it!=snifferResults_[slotId-1].end(); it++ )
    {
        if( it->earfcn_ == earfcn )
        {
            if( it->pci_>503 )
            {
                continue;
            }
            else
            {
                intraFreqNbrPciList.push_back(it->pci_);
            }
        }
    }
}

void SnifferMgr::generateInterFreqNbrList(BbuCtrl& bbu, uint16_t earfcn, std::vector<uint16_t>& interFreqList)
{
    if( bbu.getInstance().getDuplexMode()==TDD )
    {
        EMLogInfo("BBU[%d]: Get inter-freq NBR list for TDD", bbu.getInstance().getSlotId());
        interFreqList.push_back(38950);
        interFreqList.push_back(37900);
        interFreqList.push_back(38098);
        interFreqList.push_back(38400);
    }
    else
    {
        EMLogInfo("BBU[%d]: Get inter-freq NBR list for FDD", bbu.getInstance().getSlotId());
        if( bbu.getInstance().getTeleOperator()==CHINA_TELECOM )
        {
            EMLogInfo("BBU[%d]: CHINA_TELECOM", bbu.getInstance().getSlotId());
            interFreqList.push_back(100);
            interFreqList.push_back(1825);
        }
        else
        {
            EMLogInfo("BBU[%d]: CHINA_UNICOM", bbu.getInstance().getSlotId());
            interFreqList.push_back(500);
            interFreqList.push_back(1650);
        }
    }

    for(std::vector<uint16_t>::iterator it=interFreqList.begin(); it!=interFreqList.end(); it++)
    {
        if( *it==earfcn )
        {
            it = interFreqList.erase(it);
        }

        if( it==interFreqList.end() )
        {
            break;
        }
    }

}

void SnifferMgr::packSnifferResult(BbuCtrl& bbu, uint8_t* buffer, uint32_t& length)
{
    packSnifferResult(bbu.getInstance().getSlotId(), buffer, length);
}

void SnifferMgr::packSnifferResult(uint8_t slotId, uint8_t* buffer, uint32_t& length)
{
    if( buffer==NULL )
    {
        EMLogError("buffer is NULL");
        return;
    }

    if( !BbuManagerPtr->isSlotIdValid(slotId) )
    {
        return;
    }

    uint8_t* ptr = buffer;
    length = 0;

    std::vector<NmmResult>& result = snifferResults_[slotId-1];
    for(size_t i=0; i<result.size(); i++)
    {
        memcpy(ptr, &(result[i].earfcn_), sizeof(result[i].earfcn_));
        ptr += sizeof(result[i].earfcn_);
        length += sizeof(result[i].earfcn_);

        memcpy(ptr, &(result[i].pci_), sizeof(result[i].pci_));
        ptr += sizeof(result[i].pci_);
        length += sizeof(result[i].pci_);

        memcpy(ptr, &(result[i].tac_), sizeof(result[i].tac_));
        ptr += sizeof(result[i].tac_);
        length += sizeof(result[i].tac_);

        memcpy(ptr, &(result[i].rssi_), sizeof(result[i].rssi_));
        ptr += sizeof(result[i].rssi_);
        length += sizeof(result[i].rssi_);

        memcpy(ptr, &(result[i].priority_), sizeof(result[i].priority_));
        ptr += sizeof(result[i].priority_);
        length += sizeof(result[i].priority_);
    } 
}


void SnifferMgr::indicateBbuDeactive(BbuCtrl& bbu)
{
    EMLogInfo("BBU[%d]: indicateBbuDeactive", bbu.getInstance().getSlotId());

    SnifferProcedure* proc = procedures_[bbu.getInstance().getSlotId()-1];
    if( proc->isActive() )
    {
        if( !proc->isPrepare() )
        {
            EMLogWarning("BBU[%d]: BBU down accidentally, break sniffer", bbu.getInstance().getSlotId());

            if( proc->snfTrigger_==AUTO_SNF_TRIGGER )
            {
                autoSnfCtrls_[bbu.getInstance().getSlotId()-1]->indicateBbuDeactive();
            }
            proc->stopProcedure();
            openTxPwer();
        }
        else
        {
            EMLogInfo("BBU[%d]: BBU down, SNF prepare is on going, wait", bbu.getInstance().getSlotId());
            proc->waitForBbuConn();
        }
    }

    if( prepareProc_.isActive() )
    {
        prepareProc_.indicateBbuDeactive(bbu);
    }
}

void SnifferMgr::indicateBbuActive(BbuCtrl& bbu)
{
    EMLogInfo("BBU[%d]: indicateBbuActive", bbu.getInstance().getSlotId());

    SnifferProcedure* proc = procedures_[bbu.getInstance().getSlotId()-1];

    proc->stopBbuConnTimer();
}

NmmResult* SnifferMgr::findStrongestRssi(std::vector<NmmResult>& resultList, std::set<uint8_t>& bandSpec)
{
    NmmResult* result = NULL;

    if( resultList.empty() )
    {
        return result;
    }

    std::vector<NmmResult>::iterator rssiStrongestIt = resultList.begin();
    for( std::vector<NmmResult>::iterator vit = resultList.begin(); vit!=resultList.end(); vit++ )
    {
        EMLogInfo("Results: earfcn[%d] - pci[%d] - tac[%d] - rssi[%d]", vit->earfcn_, vit->pci_, vit->tac_, vit->rssi_);

        if( bandSpec.count(BandDataPtr->getBandFromEarfcn(vit->earfcn_))==0 )
        {
            continue;
        }
        if( vit->rssi_==0xffff || vit->pci_==0xffff )
        {
            continue;
        }

        if( rssiStrongestIt->rssi_==0xffff || rssiStrongestIt->pci_==0xffff )
        {
            rssiStrongestIt = vit;
            continue;
        }

        if( vit->rssi_ > rssiStrongestIt->rssi_ )
        {
            rssiStrongestIt = vit;
        }
    }

    if( rssiStrongestIt->rssi_==0xffff )
    {
        EMLogInfo("Rssi of all cells are 0xffff");
    }
    else if( rssiStrongestIt->pci_ >=504 )
    {
        EMLogError("Invalid pci[%d]", rssiStrongestIt->pci_);
    }
    else
    {
        result = &(*rssiStrongestIt);
    }

    return result;
}

std::vector<NmmResult> SnifferMgr::findHPriority(std::vector<NmmResult>& resultList, std::set<uint8_t>& bandSpec)
{
    std::vector<NmmResult> hPriorityResults;

    if( resultList.empty() )
    {
        return hPriorityResults;
    }

    uint16_t hpriority = resultList.begin()->priority_;

    for( std::vector<NmmResult>::iterator vit = resultList.begin(); vit!=resultList.end(); vit++ )
    {
        EMLogInfo("Results: earfcn[%d] - pci[%d] - tac[%d] - rssi[%d] - priority[%d]", vit->earfcn_, vit->pci_, vit->tac_, vit->rssi_, vit->priority_);

        if( bandSpec.count(BandDataPtr->getBandFromEarfcn(vit->earfcn_))==0 )
        {
            continue;
        }

        if( vit->priority_ > hpriority )
        {
            hPriorityResults.clear();
            hPriorityResults.push_back(*vit);
        }
        else if( vit->priority_==hpriority )
        {
            hPriorityResults.push_back(*vit);
        }
    }

    return hPriorityResults;
}

NmmResult* SnifferMgr::findStrongestRssi(std::vector<NmmResult>& resultList)
{
    NmmResult* result = NULL;

    if( resultList.empty() )
    {
        return result;
    }

    std::vector<NmmResult>::iterator rssiStrongestIt = resultList.begin();
    for( std::vector<NmmResult>::iterator vit = resultList.begin(); vit!=resultList.end(); vit++ )
    {
        EMLogInfo("Results: earfcn[%d] - pci[%d] - tac[%d] - rssi[%d]", vit->earfcn_, vit->pci_, vit->tac_, vit->rssi_);
            
        if( vit->rssi_==0xffff || vit->pci_==0xffff )
        {
            continue;
        }

        if( rssiStrongestIt->rssi_==0xffff || rssiStrongestIt->pci_==0xffff )
        {
            rssiStrongestIt = vit;
            continue;
        }

        if( vit->rssi_ > rssiStrongestIt->rssi_ )
        {
            rssiStrongestIt = vit;
        }
    }

    if( rssiStrongestIt->rssi_==0xffff )
    {
        EMLogInfo("Rssi of all cells are 0xffff");
    }
    else if( rssiStrongestIt->pci_ >=504 )
    {
        EMLogError("Invalid pci[%d]", rssiStrongestIt->pci_);
    }
    else
    {
        result = &(*rssiStrongestIt);
    }
    return result;
}

void SnifferMgr::configCellToBbu(BbuCtrl& bbu)
{
    std::set<uint8_t> bandSpt;
    bbu.getInstance().getSupportedBands(bandSpt);
    if( bandSpt.empty() )
    {
        EMLogError("Invalid empty band support list");
        return;
    }

    bool builtInCellCfgUsage = false;
    std::vector<NmmResult> hpResults = findHPriority(snifferResults_[bbu.getInstance().getSlotId()-1], bandSpt);
    NmmResult* result = findStrongestRssi(hpResults, bandSpt);
    if( result==NULL )
    {
        EMLogInfo("No cell of compatible RSSI found");
        builtInCellCfgUsage = true;
    }

    std::vector<uint16_t> nbrCellList;
    std::vector<uint16_t> interFreqNbrList;

    uint16_t dlArfcn = bbu.getWorkingDlArfcn();
    uint16_t ulArfcn = bbu.getWorkingUlArfcn();
    uint16_t simCellPci = bbu.getWorkingPci();
    uint16_t tac = bbu.getWorkingTac();
    std::vector<uint32_t> plmnIdList = bbu.getWorkingPlmnList();
    bool isMeasEnable = bbu.getWorkingMeasEnable();

    if( !builtInCellCfgUsage )
    {
        EMLogInfo("BBU[%d]: Use sniffer result", bbu.getInstance().getSlotId());
        
        generateIntraFreqNbrList(bbu, dlArfcn, nbrCellList);
        generateInterFreqNbrList(bbu, dlArfcn, interFreqNbrList);

        if( procedures_[bbu.getInstance().getSlotId()-1]->snfTrigger_==AUTO_SNF_TRIGGER )
        {
            dlArfcn = result->earfcn_;
            simCellPci = (result->pci_+1)%504;

            srand(time(NULL));
            tac = result->tac_ + (rand()%100);
			if( bbu.getInstance().getDuplexMode()==TDD )
			{
				ulArfcn = dlArfcn;
			}
			else
			{
				ulArfcn = dlArfcn + 18000;
			}
            //plmnIdList.clear();
            //plmnIdList.push_back(0x46000f);
			bbu.setWorkingCellInfo(dlArfcn, dlArfcn, simCellPci, tac, plmnIdList, NULL, false);

            EMLogInfo("BBU[%d]: config cell under auto snf.", bbu.getInstance().getSlotId());
        }
    }
    else
    {
        generateInterFreqNbrList(bbu, dlArfcn, interFreqNbrList);

        EMLogInfo("BBU[%d]: builtInCellCfgUsage", bbu.getInstance().getSlotId());

        if( procedures_[bbu.getInstance().getSlotId()-1]->snfTrigger_==AUTO_SNF_TRIGGER )
        {
/*
            if( bbu.getInstance().IsBandSupported(9) )
            {
                dlArfcn = 3800;
            }
            else if( bbu.getInstance().IsBandSupported(38) )
            {
                dlArfcn = 37750;
            }
            else if( bbu.getInstance().IsBandSupported(39) )
            {
                dlArfcn = 38250;
            }
            else 
            {
                dlArfcn = 38650;
            }

            simCellPci = 2;
*/
			if( !bbu.getSnifferArfcn().empty() )
			{
				dlArfcn = *bbu.getSnifferArfcn().begin();
			}
			simCellPci = 2;
            srand(time(NULL));
            tac = 9508 + (rand()%100);
           // plmnIdList.clear();
           // plmnIdList.push_back(0x46000f);
			if( bbu.getInstance().getDuplexMode()==TDD )
			{
				ulArfcn = dlArfcn;
			}
			else
			{
				ulArfcn = dlArfcn + 18000;
			}
            //plmnIdList.clear();
            //plmnIdList.push_back(0x46000f);
			bbu.setWorkingCellInfo(dlArfcn, dlArfcn, simCellPci, tac, plmnIdList, NULL, false);
			EMLogInfo("BBU[%d]: config cell under auto snf.", bbu.getInstance().getSlotId());
        }
    }
    

    EMLogInfo("BBU[%d]: working dlArfcn[%d] ulArfcn[%d] pci[%d] TAC[%d] isMeasEnable[%d]", bbu.getInstance().getSlotId(), dlArfcn, ulArfcn, simCellPci, tac, isMeasEnable);

    for(size_t i=0; i<plmnIdList.size(); i++)
    {
        EMLogInfo("BBU[%d]: PLMN[0x%x]", bbu.getInstance().getSlotId(), plmnIdList[i]); 
    }
    NmmToX86Protocol_CellConfig cellConfigMsg;
    EutranMgrPtr->reportUsingEarfcn(bbu.getInstance().getSlotId(), dlArfcn);
    if( !cellConfigMsg.pack(dlArfcn, ulArfcn, simCellPci, plmnIdList, tac, nbrCellList, interFreqNbrList) )
    {
        EMLogError("BBU[%d]: Fail to pack NmmToX86Protocol_CellConfig", bbu.getInstance().getSlotId());
        return;
    }

    cellConfigMsg.pack(isMeasEnable);

    int16_t txPwer = 0;
    if( bbu.getTxPower(txPwer) )
    {
        if( !cellConfigMsg.pack(txPwer) )
        {
            EMLogError("BBU[%d]: Fail to pack NmmToX86Protocol_CellConfig", bbu.getInstance().getSlotId());
            return;
        }
    }

    uint32_t seqNo = bbu.getInstance().allocSeqNo();
    cellConfigMsg.packSeqNum(seqNo);

    if( !bbu.getInstance().sendMessage(cellConfigMsg.getMessage()) )
    {
        EMLogError("BBU[%d]: Fail to send NmmToX86Protocol_CellConfig", bbu.getInstance().getSlotId());
        return;
    }
    StateReportProcedurePtr->reportState(bbu, BBU_CELL_CFG);
   
}

void SnifferMgr::processNmmStatusResponse(NmmToX86Protocol_NmmStatusRpt& rpt)
{
    uint32_t recvSeqNo = 0;
    if( !rpt.unpackSeqNum(recvSeqNo) )
    {
        EMLogWarning("Fail to unpack seq no");
    }

    std::vector<WrapperCmdPara> paras;

    NmmStatus rc = NMM_STATUS_INVALID;
    if( !rpt.unpack(rc) )
    {
        EMLogWarning("Fail to unpack NmmStatus");
        if( isCurrentProcTrigByOam_ )
        {
            isCurrentProcTrigByOam_ = false;
            paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_UNAVAIL)));
            EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, paras);
        }
        else
        {
            EMLogInfo("Nmm status request is not triggerd by OAM, rc=%d", rc);
        }
        return;
    }
        
    if( isCurrentProcTrigByOam_ )
    {
        isCurrentProcTrigByOam_ = false;
        switch(rc)
        {
            case NMM_STATUS_INVALID:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_UNAVAIL)));
                break;
            }
            case NMM_STATUS_IDLE:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_IDLE)));
                break;
            }
            case NMM_STATUS_RSSI:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_RSSI_MEASING)));
                break;
            }
            case NMM_STATUS_CELL_SEARCH:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_CELL_SEARCH)));
                break;
            }
            case NMM_STATUS_MIB:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_MIB_READING)));
                break;
            }
            case NMM_STATUS_SIB1:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_SBI1_READING)));
                break;
            }
            case NMM_STATUS_SIBX:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_SBIX_READING)));
                break;
            }
            case NMM_STATUS_FINISH:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_FINISH)));
                break;
            }
            default:
            {
                paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_STATUS, static_cast<uint32_t>(PARA_VALUE_EUTRAN_BBU_SNIFFER_STATUS_UNAVAIL)));
                break;
            }
        }
        EutranMgrPtr->responseToSrcModule(CMD_SET_RESPONSE, paras);
    }
    else
    {
        EMLogInfo("Nmm status request is not triggerd by OAM, rc=%d", rc);
    }
}

bool SnifferMgr::processTxPwerDbRsp(BbuCtrl& bbu, OamMessageProtocol_TxPowerDbmConfigRsp& rsp)
{
    if( prepareProc_.isProcedureDone() )
    {
        return true;
    }
    return prepareProc_.processTxPwerDbRsp(bbu, rsp);
}

bool SnifferMgr::processBbuStateRsp(BbuCtrl& bbu, OamMessageProtocol_SysStatusRsp& rsp)
{
    if( prepareProc_.isProcedureDone() )
    {
        return true;
    }
    return prepareProc_.processBbuStateRsp(bbu, rsp);
}

void SnifferMgr::handleSnfResult(BbuCtrl& bbu)
{
    if( isAutoCfgCell_ )
    {     
        EMLogInfo("BBU[%d]: auto config cell", bbu.getInstance().getSlotId());
        configCellToBbu(bbu);
    }

    EMLogInfo("BBU[%d]: report SNF result", bbu.getInstance().getSlotId());
    uint8_t buf[65535];
    memset(buf, 0, sizeof(buf));

    uint32_t length = 0;
    packSnifferResult(bbu, buf, length);
        
    std::vector<WrapperCmdPara> paras;
    paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_BBU_SLOT_ID, static_cast<uint8_t>(bbu.getInstance().getSlotId())));
    paras.push_back(WrapperCmdPara(PARA_TYPE_EUTRAN_SNIFFER_RESULT, length, buf));
    EutranMgrPtr->reportInfo(CMD_EVT_EUTRAN_SNIFFER_RESULT, paras);
}

void SnifferMgr::openTxPwer()
{
	if (BbuManagerPtr->isLocationMode())
	{
		EMLogInfo("eutran working mode is location");
		return;
	}
    if( isSniffering() )
    {
        EMLogInfo("Sniffer still on going");
        return;
    }

    for(uint8_t i=1; i<=BbuManager::MAX_BBU_INSTANCES; i++)
    {
        BbuCtrl* bbu = BbuManagerPtr->getBbu(i);
        if( bbu==NULL )
        {
            EMLogError("Fail to get BBU[%d]", static_cast<uint32_t>(i));
            continue;
        }
#ifdef LOCATION_DEVICE
        if( (bbu->isLocationEnable()) && (bbu->isWorking()))
#else
        if( bbu->isWorking() )
#endif
        {
            int8_t txPwDb = EutranConfigDataPtr->getTxPowerDb(bbu->getInstance().getSlotId());
            EMLogInfo("BBU[%d]: open TX power[%d]", bbu->getInstance().getSlotId(), static_cast<int32_t>(txPwDb));
            
            bbu->buildAndSendTxPowerDb(txPwDb);
        }
    }
}

bool SnifferMgr::delAutoSnfCfg(uint8_t slotId)
{
    if( !BbuManagerPtr->isSlotIdValid(slotId) )
    {
        return false;
    }

    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    EMLogInfo("BBU[%d]: delete auto sniffer configuration", bbu->getInstance().getSlotId());

    AutoSnifferCtrl* snfCtrl = autoSnfCtrls_[slotId-1];
    snfCtrl->stop();

    return true;
}

bool SnifferMgr::startAutoSnf(uint8_t slotId, uint16_t rssi, std::vector<EarfcnRangeType>& range, uint16_t day, uint8_t hour, uint8_t min)
{
    EMLogInfo("BBU[%d]: Start auto sniffer. RSSI[%d] day[%d] hour[%d] min[%d]", static_cast<uint16_t>(slotId), rssi, day, static_cast<uint32_t>(hour), static_cast<uint32_t>(min));
    if( !BbuManagerPtr->isSlotIdValid(slotId) )
    {
        return false;
    }

    AutoSnifferCtrl* snfCtrl = autoSnfCtrls_[slotId-1];
    snfCtrl->stop();
    snfCtrl->arfcnRange_ = range;

    AutoSnfByTime* strategy = new AutoSnfByTime();
    if( strategy==NULL )
    {
        EMLogError("BBU[%d]: Fail to allocate buffer", static_cast<uint16_t>(slotId));
        return false;
    }

    if( !strategy->setStartTime(day, hour, min) )
    {
        EMLogError("BBU[%d]: Fail to set time", static_cast<uint16_t>(slotId));
        return false;
    }

    if( !snfCtrl->start(strategy) )
    {
        EMLogError("BBU[%d]: Fail to start auto sniffer", static_cast<uint16_t>(slotId));
        return false;
    }

    return true;
}

bool SnifferMgr::startSnfWithoutPrepareProc(uint8_t snifferType, uint8_t slotId, const std::vector<EarfcnRangeType>& range)
{
    BbuCtrl* bbu = BbuManagerPtr->getBbu(slotId);
    if( bbu==NULL )
    {
        EMLogError("BBU ctrl pointer is NULL, slotId=%d", static_cast<uint32_t>(slotId));
        return false;
    }

    if( !bbu->getInstance().isActive() )
    {
        EMLogError("BBU[%d]: BBU is deactive", static_cast<uint32_t>(slotId));
        return false;
    }

    SnifferProcedure* pro = procedures_[slotId-1];
    if( pro->isActive() )
    {
        EMLogError("BBU[%d]: SnifferProcedure is active", bbu->getInstance().getSlotId());
        return false;
    }
    pro->snfTrigger_ = AUTO_SNF_TRIGGER;
    if (snifferType == OAM_SNF_TRIGGER)
    {
	    pro->snfTrigger_ = OAM_SNF_TRIGGER;
    }
    std::copy(range.begin(), range.end(), std::back_inserter(pro->arfcnRange_));

    snifferResults_[slotId-1].clear();
    if (pro->startSniffer())
	{
		EMLogInfo("BBU[%d] sniffer start success", slotId);
		EutranMgrPtr->responseSuccess();
	}
	else
	{
		EMLogInfo("BBU[%d] sniffer start failed", slotId);
		EutranMgrPtr->responseFailure();

	}
    return true;
}
